<?php

/**
 * 作者：云喵软件开发工作室
 * 官网：https://www.meoyun.com
 */

namespace app\common\controller;

use app\BaseController;
use AlibabaCloud\Credentials\Credential;
use app\model\PlatformConfigModel;
use DateInterval;
use DateTime;
use DateTimeZone;
use Exception;

class AlibabaCloud extends BaseController
{

    public function credential()
    {
        try {
            $config = PlatformConfigModel::getConfig("aliyun_oss");

            $region = $config["regionId"];
            $bucket = $config["bucket"];
            $product = 'oss';
            $accessKeyId = $config["accessKeyId"];
            $accessKeySecret = $config["accessKeySecret"];
            $roleArn = $config["roleArn"];
            $host = "https://$bucket.oss-$region.aliyuncs.com";

            // 创建阿里云凭证配置
            $config = new Credential\Config([
                'type' => 'ram_role_arn',
                'accessKeyId' => $accessKeyId,
                'accessKeySecret' => $accessKeySecret,
                'roleArn' => $roleArn,
                'roleSessionName' => 'role_session_name',
                'policy' => '',
                // 设置临时访问凭证过期时间为3600秒
                'roleSessionExpiration' => 3600,
            ]);

            // 根据配置创建凭证对象
            $credential = new Credential($config);

            // 从凭证对象中获取凭证信息
            $cred = $credential->getCredential();

            // 获取当前的 UTC 时间
            $utcTime = new DateTime('now', new DateTimeZone('UTC'));
            // 格式化当前日期为 Ymd 格式，例如 20240101
            $date = $utcTime->format('Ymd');
            // 克隆当前时间对象，用于设置过期时间
            $expiration = clone $utcTime;
            // 设置过期时间为当前时间往后 1 小时
            $expiration->add(new DateInterval('PT1H'));
            // 构建policy
            $policyMap = [
                "expiration" => $expiration->format('Y-m-d\TH:i:s.000\Z'),
                "conditions" => [
                    ["bucket" => $bucket],
                    ["x-oss-signature-version" => "OSS4-HMAC-SHA256"],
                    ["x-oss-credential" => sprintf("%s/%s/%s/%s/aliyun_v4_request", $cred->getAccessKeyId(), $date, $region, $product)],
                    ["x-oss-date" => $utcTime->format('Ymd\THis\Z')],
                    ["x-oss-security-token" => $cred->getSecurityToken() ?? ''],
                ],
            ];
            // 将policy转换为 JSON 格式的字符串
            $policy = json_encode($policyMap);
            // 对policy字符串进行 Base64 编码，得到待签名的字符串
            $stringToSign = base64_encode($policy);

            // 构建signingKey，由固定字符串 "aliyun_v4" 和访问密钥 Secret 拼接而成
            $signingKey = "aliyun_v4" . $cred->getAccessKeySecret();
            $h1Key = hash_hmac('sha256', $date, $signingKey, true);
            $h2Key = hash_hmac('sha256', $region, $h1Key, true);
            $h3Key = hash_hmac('sha256', $product, $h2Key, true);
            $h4Key = hash_hmac('sha256', 'aliyun_v4_request', $h3Key, true);

            // 使用 h4Key 对待签名的字符串进行 HMAC-SHA256 签名，得到最终的签名
            $signature = hash_hmac('sha256', $stringToSign, $h4Key);

            // 构建响应给前端的表单数据，包含policy、签名版本、凭证、日期、签名和安全令牌等信息
            $responseData = [
                'policy' => $stringToSign,
                "x_oss_signature_version" => "OSS4-HMAC-SHA256",
                "x_oss_credential" => sprintf("%s/%s/%s/%s/aliyun_v4_request", $cred->getAccessKeyId(), $date, $region, $product),
                "x_oss_date" => $utcTime->format('Ymd\THis\Z'),
                "signature" => $signature,
                "security_token" => $cred->getSecurityToken() ?? '',
                "host" => $host,
            ];

            return $this->success($responseData);

        } catch (Exception $e) {
            return $this->fail($e->getMessage());
        }
    }
}